/**
 * Android Speech Diarization - Calculates the amount of time spent speaking
 * 								by each speaker in a conversation
 * 
 * Copyright (C) 2011  Daniel Di Matteo
 *
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package mfccExtraction;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.LinkedList;
import java.util.List;

import edu.cmu.sphinx.frontend.Data;
import edu.cmu.sphinx.frontend.DataEndSignal;
import edu.cmu.sphinx.frontend.DoubleData;
import edu.cmu.sphinx.frontend.FrontEnd;
import edu.cmu.sphinx.frontend.util.StreamDataSource;
import edu.cmu.sphinx.util.props.ConfigurationManager;

public class MfccMaker {
	String configFile;
	String inputAudioFile;
	String outputMfccFileLearn;
	String outputMfccFilePredict;

	LinkedList<String> lastMFCC;

	public LinkedList<String> getLastMFCC() {
		return lastMFCC;
	}


	public MfccMaker(String config, String audio, String outputMFCCLearn, String outputMFCCPredict){
		configFile = config;
		inputAudioFile = audio;
		outputMfccFileLearn = outputMFCCLearn;
		outputMfccFilePredict = outputMFCCPredict;

	}

	private LinkedList<String> getRaw(List<float[]> allFeatures) {

		LinkedList<String> outputLine = new LinkedList<String>();

		String lineOfResult = "";


		for(float[] line : allFeatures)
		{
			for(float value : line)
			{
				lineOfResult += value + ";";
			}
		}
		
		outputLine.add(lineOfResult);
		lineOfResult ="";

		return outputLine;
	}
	
	
//	private LinkedList<String> getMedianes(List<float[]> allFeatures) {
//
//		LinkedList<String> outputLine = new LinkedList<String>();
//
//		String lineOfResult = "";
//
//		Set<Float> column = new TreeSet<Float>();
//
//		//Load the x measures of 13 mfcc's in an array
//		for(int cptCol = 0; cptCol <13; cptCol++)
//		{
//
//			for(float[] line : allFeatures)
//			{
//				column.add(line[cptCol]);
//			}
//
//			float medianne;
//			if(column.size()%2 == 0) // Si pair, medianne c'est la moyenne des deux du milieu
//			{
//				medianne = (Float) column.toArray()[column.size()/2] + (Float) column.toArray()[(column.size()/2)+1];
//				medianne /= 2;
//			}
//			else // Sinon c'est la valeure du centre
//			{
//				medianne = (Float) column.toArray()[column.size()/2+1];
//
//			}
//			lineOfResult += medianne +";";
//			column.clear();
//		}
//		outputLine.add(lineOfResult);
//
//		return outputLine;
//	}


	public void produceFeatures(String wordAssociated, Integer nbOutputs){
		FrontEnd frontEnd = null;
		StreamDataSource audioSource = null;
		List<float[]> allFeatures;
		int featureLength = -1;

		ConfigurationManager cm = new ConfigurationManager(configFile);

		try {
			frontEnd = (FrontEnd) cm.lookup("mfcFrontEnd");
			audioSource = (StreamDataSource) cm.lookup("streamDataSource");
		} catch (Exception e) {
			e.printStackTrace();
		}

		//set source for streaming in audio
		try {
			audioSource.setInputStream(new FileInputStream(inputAudioFile), "audio");
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		allFeatures = new LinkedList<float[]>();

		//get features from audio
		try {
			assert (allFeatures != null);

			LinkedList<String> capture = new LinkedList<String>();
			Data feature = frontEnd.getData();

			while (!(feature instanceof DataEndSignal)) {
				if (feature instanceof DoubleData) {
					double[] featureData = ((DoubleData) feature).getValues();
					if (featureLength < 0) {
						featureLength = featureData.length;
						//logger.info("Feature length: " + featureLength);
					}
					float[] convertedData = new float[featureData.length];
					String line="";
					for (int i = 0; i < featureData.length; i++) {
						convertedData[i] = (float) featureData[i];
						line += featureData[i]+";";
					}
					capture.add(line);
					allFeatures.add(convertedData);
				}
				feature = frontEnd.getData();
			}

			lastMFCC = getRaw(allFeatures);
			if(wordAssociated != null)
			{
				lastMFCC.set(0, lastMFCC.get(0) + wordAssociated);
				FileManager.ecrireFichier(outputMfccFileLearn, lastMFCC);
			}
			else
			{
				new File(outputMfccFilePredict).delete();
				//Add a junk output
				lastMFCC.set(0, lastMFCC.get(0).replace(';', '\t'));			
				FileManager.ecrireFichier(outputMfccFilePredict, lastMFCC );
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return;
	}
}